package com.dao.database;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Calendar;
import java.util.Iterator;
import java.util.Locale;

import org.apache.log4j.Logger;

import com.dao.database.exceptions.DataAccessException;
import com.dao.database.exceptions.NoLoadMethodException;

public class StockDataDao{

	private final static Logger LOGGER = Logger.getLogger(StockDataDao.class
			.getName());

	
	public StockDataDao() {
	}

	public void loadData(StockObject obj, String fileName,
			SpecyficObjectDAO dao, String source) throws NoLoadMethodException, DataAccessException, IOException {
		LOGGER.trace("method: loaddata("+obj+","+fileName+","+dao+","+source+")");
		clearHistoricalData(obj.getObjId(),dao);
		Calendar cal = Calendar.getInstance(Locale.ROOT);
		cal.set(Calendar.YEAR, 1940);
		cal.set(Calendar.DAY_OF_YEAR, 1);
		loadDataFromDate(obj,fileName,dao,source,cal);
	}
	private void loadDataFromDate(StockObject obj, String fileName,
	SpecyficObjectDAO dao, String source,Calendar day) throws NoLoadMethodException,DataAccessException, IOException{
		LOGGER.trace("method: loadDataFromDate("+obj+","+fileName+","+dao+","+source+","+day+")");
		LOGGER.debug("The dao is type: "+dao.getSpecificObjectName());
		if(dao.getSpecificObjectName().contentEquals(StockCompany.TYPE) && obj.getStockObjType().contentEquals(StockCompany.TYPE)){
			if(StockCompanyDao.companyHistoricalDataYahoo.contentEquals(source)){
				Calendar today=Calendar.getInstance(Locale.ROOT);
				String fromYear=String.valueOf(day.get(Calendar.YEAR));
				String toYear=String.valueOf(today.get(Calendar.YEAR));
				String fromMonth=String.valueOf(day.get(Calendar.MONTH));
				String toMonth=String.valueOf(today.get(Calendar.MONTH));
				String fromDay=String.valueOf(day.get(Calendar.DAY_OF_MONTH));
				String toThatDay=String.valueOf(today.get(Calendar.DAY_OF_MONTH));
				URL yahooHist;
				String url="http://ichart.finance.yahoo.com/table.csv?s="
						+ obj.getStockObjTicker() + "&d="+toMonth+"&e="+toThatDay+"&f="+toYear+"&g=d&a="+fromMonth+"&b="+fromDay+"&c="+fromYear+"&ignore=.csv";
				try {
					yahooHist = new URL(url);
					URLConnection yc = yahooHist.openConnection();
					BufferedReader in = new BufferedReader(new InputStreamReader(
							yc.getInputStream()));
					LOGGER.debug("in null: " + (in==null));
					dao.batchSetVariablesData(in, obj.getStockObjId(), source);
				} catch (MalformedURLException e) {
					LOGGER.error("bad URL"+url, e);
				} 

			}
			
		}
		else if(dao.getSpecificObjectName().contentEquals(StockIndex.TYPE)&& obj.getStockObjType().contentEquals(StockIndex.TYPE)){
			if(StockIndexDao.indexHistoricalDataStooq.contentEquals(source)){
				/**
				 * Tutaj troszke oszukujemy, zawsze ladujemy caly plik a nie tylko
				 * od momentu ostatniej daty,
				 * Od pliku zalezy czy dane beda aktualne
				 */
				clearHistoricalData(obj.getObjId(),dao);
				FileReader fr;
				fr = new FileReader(fileName);
				BufferedReader reader = new BufferedReader(fr);
				dao.batchSetVariablesData(reader,obj.getStockObjId(), source);
			}
		}
		else
			throw new NoLoadMethodException("There is no method for object "+obj.getStockObjType()+
					"and source "+source);
		
		
	}


	public void refreshData(StockObject obj, String fileName,
			SpecyficObjectDAO dao, String source) throws NoLoadMethodException, DataAccessException, IOException {
		LOGGER.trace("method: refreshData("+obj+","+fileName+","+dao+","+source+")");
		Calendar today=Calendar.getInstance();
		today.add(Calendar.DAY_OF_YEAR, -1);
		Calendar latestDate=getLatestDate(obj,dao);
		LOGGER.debug("Yesterday: "+ today.get(Calendar.DAY_OF_MONTH)+ " and last date: "+latestDate.get(Calendar.DAY_OF_MONTH));
		if((today.get(Calendar.YEAR)!=latestDate.get(Calendar.YEAR))|| 
				(today.get(Calendar.DAY_OF_YEAR)!=latestDate.get(Calendar.DAY_OF_YEAR))){
			latestDate.add(Calendar.DAY_OF_YEAR, 1);
			loadDataFromDate(obj,fileName,
					dao,source,latestDate);
		}
			
		else
			LOGGER.debug("The data is current");		
	}
	private Calendar getLatestDate(StockObject obj,SpecyficObjectDAO dao){
		LOGGER.trace("method: getLatestDate("+obj+","+dao+")");
		Calendar cal= Calendar.getInstance(Locale.ROOT);
		Iterator<PredictableObject.Variable>iter=obj.getVariableMap().values().iterator();
		while(iter.hasNext()){
			PredictableObject.Variable var=iter.next();
			if(isDataCurrent(obj,var.getVariableName(),dao)){
				int[] var_last_date=dao.getObjectVariableLastDate(obj.getStockObjId(),var.getVariableId());
				Calendar cal2=Calendar.getInstance();
				cal2.set(Calendar.YEAR, var_last_date[0]);
				cal2.set(Calendar.DAY_OF_YEAR, var_last_date[1]);
				if(cal2.get(Calendar.YEAR)<cal.get(Calendar.YEAR))
					cal=cal2;
				else {
					if(cal2.get(Calendar.DAY_OF_YEAR)<cal.get(Calendar.DAY_OF_YEAR))
					cal=cal2;
				}
			}
		}
		return cal;
	}
	private boolean isDataCurrent(StockObject obj,
			String variableName,SpecyficObjectDAO dao){
		LOGGER.trace("method: getLatestDate("+obj+","+variableName+","+dao+")");
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.DATE, -1);
		Calendar dbDate=Calendar.getInstance();
		int[] var_last_date=dao.getObjectVariableLastDate(obj.getStockObjId(),obj.getVariable(variableName).getVariableId());
		dbDate.set(Calendar.YEAR, var_last_date[0]);
		dbDate.set(Calendar.DAY_OF_YEAR, var_last_date[1]);
		if(dbDate.get(Calendar.YEAR)!=cal.get(Calendar.YEAR) && dbDate.get(Calendar.DAY_OF_YEAR)!=cal.get(Calendar.DAY_OF_YEAR)){
			if(dbDate.get(Calendar.DAY_OF_WEEK)==Calendar.FRIDAY && (cal.get(Calendar.DAY_OF_WEEK)==Calendar.SATURDAY 
					|| cal.get(Calendar.DAY_OF_WEEK)==Calendar.SUNDAY) )
				return true;
			else
				return false; 
		}
		else
		return true;
	}


	public void loadObjects(String fileName,
			SpecyficObjectDAO dao, String source) throws IOException,DataAccessException, NoLoadMethodException {
		LOGGER.trace("method: loadObjects("+fileName+","+dao+","+source+")");	
		if( source.contentEquals(StockCompanyDao.companyTickerListEoddata)&& 
				dao.getSpecificObjectName().contentEquals(StockCompany.TYPE)){
			
				FileReader fr = new FileReader(fileName);
				BufferedReader reader = new BufferedReader(fr);
				dao.batchCreateObjects(reader, source);
		}
		else
			throw new NoLoadMethodException("There is no method for dao "+dao.getSpecificObjectName()+
					"and source "+source);
			
			
	}
	
	private void clearHistoricalData(int objId, SpecyficObjectDAO dao){
		LOGGER.trace("method: clearHistoricalData("+objId+","+dao+")");
		dao.clearVariablesData(objId);
	}

}
